﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows;
using System.Windows.Controls;
using BindableDataGrid.Data;
using Combinatorics;
using SilveR.DataValidators;
using SilveR.GUIValidators;

namespace SilveR.Views.StatsViews
{
    public partial class SingleMeasureGLM : UserControl, IAnalysis
    {
        private SingleMeasureGLMVariables glmVariables;

        public SingleMeasureGLM()
        {
            InitializeComponent();

            glmVariables = new SingleMeasureGLMVariables();
            this.DataContext = glmVariables;
        }

        private void cboData_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            DataHandler dh = (DataHandler)cboData.SelectedItem;

            if (dh != null)
                glmVariables.AvailableVariables = dh.GetVariableList();
        }

        private void Target_ItemDragCompleted(object sender, ItemDragEventArgs e)
        {
            //ensure that the available variables stay sorted...
            SortableObservableCollection<ColumnInfo> availableVariables = (SortableObservableCollection<ColumnInfo>)lstAvailableVariables.ItemsSource;
            availableVariables.Sort(new ColumnIndexComparer());

            //redetermine the interactions
            glmVariables.Interactions = glmVariables.DetermineInteractions(glmVariables.TreatmentColumnNames).ToObservableCollection();

            //now that something has been moved, need to refill the primary factor
            ColumnInfo currentPrimaryFactor = glmVariables.PrimaryFactor; //remember if a primary factor is already selected

            //only enable the primary factor dropdown if it has items
            if (!String.IsNullOrEmpty(glmVariables.Covariate) && cboPrimaryFactor.Items.Count > 0)
            {
                if (currentPrimaryFactor == null)
                {
                    cboPrimaryFactor.SelectedIndex = 0; //select the first treatment as the primary factor
                }
                else
                {
                    glmVariables.PrimaryFactor = currentPrimaryFactor; //reselect the previously selected primary factor
                }

                cboPrimaryFactor.IsEnabled = true;
            }
            else
            {
                cboPrimaryFactor.SelectedIndex = -1;
                cboPrimaryFactor.IsEnabled = false;
            }

            //only enable the covariate transformation dropdown if it has items
            cboResponseTransformations.IsEnabled = !String.IsNullOrEmpty(glmVariables.Response);

            //only enable the covariate transformation dropdown if it has items
            cboCovariateTransformations.IsEnabled = !String.IsNullOrEmpty(glmVariables.Covariate);

            //make sure that the effect dropdown is refilled
            string currentEffect = glmVariables.SelectedEffect; //remember if a select is already selected (have to do this as not binding directly)

            //assemble a complete list of main and interaction effects
            List<string> effects = new List<string>();
            effects.AddRange(glmVariables.TreatmentColumnNames);
            effects.AddRange(glmVariables.Interactions);

            //if the number of interaction effects is 4 or greater,
            //then only the main effects and highest order effect are to be available
            if (glmVariables.Treatments.Count >= 4)
            {
                //remove any effect that is an interaction effect
                for (int i = effects.Count - 1; i >= 0; i = i - 1)
                {
                    if (effects[i].Contains("*")) effects.Remove(effects[i]);
                }
                //add in the highest order interaction again
                effects.Add(glmVariables.Interactions[glmVariables.Interactions.Count - 1].ToString());
            }

            glmVariables.SelectedEffectList = effects.ToObservableCollection();

            if (glmVariables.SelectedEffectList.Contains(currentEffect))
            {
                glmVariables.SelectedEffect = currentEffect; //reselect the previously selected effect (if possible)
            }
            else if (cboSelectedEffect.Items.Count > 0) //else select the first effect in the list
            {
                cboSelectedEffect.SelectedIndex = 0;
            }

            //enable or disable the effects dropdown
            cboSelectedEffect.IsEnabled = glmVariables.SelectedEffectList.Count > 0;
        }

        private void oneItem_DragOverOrDrop(object sender, Microsoft.Windows.DragEventArgs e)
        {
            ListBoxDragDropTarget target = (ListBoxDragDropTarget)sender;
            ListBox lstBox = (ListBox)target.Content;

            if (lstBox.Items.Count == 1)
            {
                e.Effects = Microsoft.Windows.DragDropEffects.None;
                e.Handled = true;
            }
        }

        private void cboComparisonsBackToControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            cboControlGroup.IsEnabled = !String.IsNullOrEmpty(glmVariables.ComparisonsBackToControl);
        }

        private void cboSelectedEffect_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //enable/disable the post hoc tests depending on whether a group is selected...
            if (String.IsNullOrEmpty(glmVariables.SelectedEffect))
            {
                cbxLSMeansSelected.IsEnabled = false;
                cboAllPairwiseComparisons.IsEnabled = false;
                cboAllPairwiseComparisons.SelectedIndex = -1;
            }
            else
            {
                cbxLSMeansSelected.IsEnabled = true;
                cboAllPairwiseComparisons.IsEnabled = true;
            }

            //fill the control dropdown with the levels for the selected effect (only if not an interaction effect)
            if (!String.IsNullOrEmpty(glmVariables.SelectedEffect) && !glmVariables.SelectedEffect.Contains("*"))
            {
                cboComparisonsBackToControl.IsEnabled = true;
                string currentControlGroup = glmVariables.ControlGroup;
                cboControlGroup.ItemsSource = DataHandler.GetLevels(glmVariables.SelectedEffect);
                cboControlGroup.IsEnabled = true;

                if (!String.IsNullOrEmpty(currentControlGroup))
                {
                    glmVariables.ControlGroup = currentControlGroup;
                }
                else
                {
                    cboControlGroup.SelectedIndex = 0;
                }
            }
            else
            {
                cboComparisonsBackToControl.IsEnabled = false;
                cboControlGroup.ItemsSource = null;
                cboControlGroup.IsEnabled = false;
            }
        }

        #region IAnalysis Members

        public bool ValidateGUI()
        {
            List<ValidationResult> validationResult = new List<ValidationResult>();
            bool validatedOK = Validator.TryValidateObject(glmVariables, new ValidationContext(glmVariables, null, null), validationResult, true);

            if (!validatedOK)
            {
                ValidationMessagesWindow vmw = new ValidationMessagesWindow(validationResult);
                vmw.Show();
            }

            return validatedOK;
        }

        public event DataValidatedEventHandler DataValidated;

        public void ValidateData()
        {
            SingleMeasureGLMValidator npv = new SingleMeasureGLMValidator(glmVariables);
            bool result = npv.Validate();

            if (npv.WarningMessages.Count > 0)
            {
                ValidationMessagesWindow vmw = new ValidationMessagesWindow(npv.WarningMessages);
                vmw.Closed += new EventHandler(vmw_Closed);
                vmw.Show();
            }
            else
            {
                if (DataValidated != null)
                    DataValidated(this, new DataValidatedEventArgs(result));
            }
        }

        private void vmw_Closed(object sender, EventArgs e)
        {
            ValidationMessagesWindow vmw = (ValidationMessagesWindow)sender;

            if (DataValidated != null)
                DataValidated(this, new DataValidatedEventArgs(vmw.DialogResult.Value));
        }

        public string[] ExportData()
        {
            DataTable dtNew = this.DataHandler.DataTable.Copy();
            dtNew.Name = "ExportData";

            //Get the response, treatment and covariate columns by removing all other columns from the new datatable
            foreach (DataColumn col in this.DataHandler.DataTable.Columns)
            {
                if (glmVariables.Response != col.ColumnName && !glmVariables.TreatmentColumnNames.Contains(col.ColumnName) && !glmVariables.OtherDesignFactorColumnNames.Contains(col.ColumnName) && glmVariables.Covariate != col.ColumnName)
                {
                    dtNew.Columns.Remove(col);
                }
            }

            //ensure that all data is trimmed
            dtNew.TrimAllDataInDataTable();

            //if the response is blank then remove that row
            dtNew.RemoveBlankRow(glmVariables.Response);

            //Need to create a new column for the scatterplot data as we have to combine any interaction effects into one column
            DataColumn scatterPlot = new DataColumn("scatterPlotColumn");
            dtNew.Columns.Add(scatterPlot);
            foreach (DataRow r in dtNew.Rows) //go through each row...
            {
                string combinedEffectValue = null;
                foreach (string s in glmVariables.TreatmentColumnNames) //combine the values from each column into one string
                {
                    combinedEffectValue = combinedEffectValue + " " + r[s.Trim()];
                }

                r["scatterPlotColumn"] = combinedEffectValue.Trim(); //copy the new value to the new column
            }

            //If an interaction effect is selected then we need to combine values into single column
            if (!String.IsNullOrEmpty(glmVariables.SelectedEffect))
            {
                //create a new column and add it to the table
                DataColumn mainEffect = new DataColumn("mainEffect");
                dtNew.Columns.Add(mainEffect);

                if (glmVariables.SelectedEffect.Contains(" * ")) //then it is an interaction effect so we need to combine values from different columns
                {
                    char[] splitChar = { '*' };
                    string[] effects = glmVariables.SelectedEffect.Split(splitChar, StringSplitOptions.RemoveEmptyEntries); //get the effect names that make up the interaction effect

                    foreach (DataRow r in dtNew.Rows) //go through each row...
                    {
                        string combinedEffectValue = null;
                        foreach (string s in effects) //combine the values from each column into one string
                        {
                            combinedEffectValue = combinedEffectValue + " " + r[s.Trim()];
                        }

                        r["mainEffect"] = combinedEffectValue.Trim(); //copy the new value to the new column
                    }
                }
                else //just copy the column selected in the dropdown
                {
                    foreach (DataRow r in dtNew.Rows)
                    {
                        r["mainEffect"] = r[glmVariables.SelectedEffect].ToString();
                    }
                }
            }

            //Now do transformations...
            dtNew.TransformColumn(glmVariables.Response, glmVariables.ResponseTransformation);

            if (lstCovariate.Items.Count == 1) //check that a covariate is selected
            {
                dtNew.TransformColumn(glmVariables.Covariate, glmVariables.CovariateTransformation);
            }

            //Finally, as numeric categorical variables get misinterpreted by r, we need to go through
            //each column and put them in quotes...
            foreach (string treat in glmVariables.TreatmentColumnNames)
            {
                if (dtNew.ColumnIsNumeric(treat))
                {
                    foreach (DataRow row in dtNew.Rows)
                    {
                        row[treat] = "'" + row[treat] + "'";
                    }
                }
            }
            foreach (string odf in glmVariables.OtherDesignFactorColumnNames)
            {
                if (dtNew.ColumnIsNumeric(odf))
                {
                    foreach (DataRow row in dtNew.Rows)
                    {
                        row[odf] = "'" + row[odf] + "'";
                    }
                }
            }

            return dtNew.GetCSVArray();
        }

        public DataHandler DataHandler
        {
            get { return glmVariables.SelectedDataHandler; }
        }

        public Dictionary<string, string> GetAnalysisArguments()
        {
            Dictionary<string, string> arguments = new Dictionary<string, string>();

            //first thing to do is to assemble the model (use the GetModel method)
            arguments.Add("Model", ArgumentConverters.ConvertIllegalChars(glmVariables.GetModel())); //4

            string scatterplotModel = ArgumentConverters.ConvertIllegalChars(glmVariables.Response) + "~scatterPlotColumn";
            arguments.Add("Scatterplot Model", scatterplotModel); //5

            //assemble a model for the covariate plot (if a covariate has been chosen)...
            if (String.IsNullOrEmpty(glmVariables.Covariate)) //6
            {
                arguments.Add("Covariate Model", "NULL");
            }
            else
            {
                string covariateModel = ArgumentConverters.ConvertIllegalChars(glmVariables.Response) + "~" + ArgumentConverters.ConvertIllegalChars(glmVariables.Covariate);
                arguments.Add("Covariate Model", covariateModel);
            }

            //get transforms
            arguments.Add("Response Transformation", "\"" + glmVariables.ResponseTransformation + "\""); //7

            arguments.Add("Covariate Transformation", "\"" + glmVariables.CovariateTransformation + "\""); //8

            arguments.Add("Primary Factor", ArgumentConverters.GetNULLOrText(ArgumentConverters.ConvertIllegalChars(glmVariables.PrimaryFactorColumnName))); //9

            string treats = null;
            foreach (ColumnInfo ci in glmVariables.Treatments) treats = treats + "," + ArgumentConverters.ConvertIllegalChars(ci.ColumnName);
            arguments.Add("Treatments", treats.TrimStart(',')); //10

            string blocks = null;
            foreach (ColumnInfo ci in glmVariables.OtherDesignFactors) blocks = blocks + "," + ArgumentConverters.ConvertIllegalChars(ci.ColumnName);

            if (String.IsNullOrEmpty(blocks)) //11
                arguments.Add("Other Design Factors", "NULL");
            else
                arguments.Add("Other Design Factors", blocks.TrimStart(','));

            arguments.Add("Produce ANOVA", ArgumentConverters.GetYesOrNo(glmVariables.ANOVASelected)); //12
            arguments.Add("Produce PR Plot", ArgumentConverters.GetYesOrNo(glmVariables.PRPlotSelected)); //13
            arguments.Add("Produce Normal Plot", ArgumentConverters.GetYesOrNo(glmVariables.NormalPlotSelected)); //14
            //arguments.Add("Produce StandardisedEffects", ArgumentConverters.GetYesOrNo(glmVariables.StandardisedEffectsSelected)); //15


            arguments.Add("Significance", glmVariables.Significance); //15

            //assemble the effect model
            if (String.IsNullOrEmpty(glmVariables.SelectedEffect)) //16, //17
            {
                arguments.Add("Effect Model", "NULL");
                //arguments.Add("Selected Effect", "NULL");
            }
            else
            {
                arguments.Add("Effect Model", ArgumentConverters.ConvertIllegalChars(glmVariables.GetEffectModel()));
                //arguments.Add("Selected Effect", ArgumentConverters.ConvertIllegalChars(glmVariables.SelectedEffect));
            }

            arguments.Add("LS Means Plot Selected", ArgumentConverters.GetYesOrNo(glmVariables.LSMeansPlotSelected)); //17

            if (!String.IsNullOrEmpty(glmVariables.AllPairwise))
                arguments.Add("All Pairwise", "\"" + glmVariables.AllPairwise + "\""); //18
            else
                arguments.Add("All Pairwise", "NULL");

            if (!String.IsNullOrEmpty(glmVariables.ComparisonsBackToControl))
                arguments.Add("Back to Control", "\"" + glmVariables.ComparisonsBackToControl + "\""); //19
            else
                arguments.Add("Back to Control", "NULL");

            arguments.Add("Control Group", "\"" + glmVariables.ControlGroup + "\""); //20

            return arguments;
        }

        public string AnalysisName
        {
            get { return "Single Measure Parametric Analysis"; }
        }

        public string ScriptName
        {
            get { return "SingleMeasureGLM.R"; }
        }

        public void UpdateDataHandlers()
        {
            //remember the current data handler before updating the available variables so that it can be selected later...
            DataHandler currentDataHandler = glmVariables.SelectedDataHandler;

            App app = (App)Application.Current;
            glmVariables.AvailableDataHandlers = app.DataHandlers;

            //reselect the current handler (if any)
            glmVariables.SelectedDataHandler = currentDataHandler;
        }

        #endregion
    }

    public class SingleMeasureGLMVariables : INotifyPropertyChanged
    {
        public SingleMeasureGLMVariables()
        {
            App app = (App)Application.Current;
            availableDataHandlers = app.DataHandlers;
        }

        public string GetModel()
        {
            //assemble the model from the information in the treatment, other factors, response and covariate boxes
            string model = Response + "~";

            if (!String.IsNullOrEmpty(Covariate))
                model = model + Covariate + "+";

            foreach (ColumnInfo ci in OtherDesignFactors)
                model = model + ci.ColumnName + "+";

            foreach (ColumnInfo ci in Treatments)
                model = model + ci.ColumnName + "+";

            //determine the interactions
            List<string> factors = new List<string>(TreatmentColumnNames);
            List<string> fullInteractions = DetermineInteractions(factors);
            foreach (string s in fullInteractions)
                model = model + s.Replace(" * ", "*") + "+";

            model = model.TrimEnd('+');

            return model;
        }

        public string GetEffectModel()
        {
            //assemble the effect model
            string effectModel = Response + "~"; //add in the response

            if (!String.IsNullOrEmpty(Covariate)) //add in a covariate if one is selected
                effectModel = effectModel + Covariate + "+";

            foreach (ColumnInfo ci in OtherDesignFactors) //add in blocking factors if they are selected
                effectModel = effectModel + ci.ColumnName + "+";

            //complicated business of assembling the other part of the model from the interactions etc...

            string[] splitter = { " * " };
            List<string> interactionEffects = new List<string>(SelectedEffect.Split(splitter, StringSplitOptions.RemoveEmptyEntries));

            foreach (ColumnInfo ci in Treatments)
            {
                if (!interactionEffects.Contains(ci.ColumnName))
                {
                    effectModel = effectModel + ci.ColumnName.Trim() + "+";
                }
            }

            return effectModel + "mainEffect"; //where maineffect is the combined effect column of the selected effect in the dataset
        }

        public List<string> DetermineInteractions(List<string> listToCreateInteractionsFrom)
        {
            List<string> interactions = new List<string>();

            //for each factor, determine the combinations
            for (int i = 2; i <= listToCreateInteractionsFrom.Count; i++)
            {
                Combinations<string> combinations = new Combinations<string>(listToCreateInteractionsFrom, i, GenerateOption.WithoutRepetition);

                //for each set of combinations we need to assemble the string, with each factor separated by a *
                foreach (IList<string> c in combinations)
                {
                    string interaction = null;

                    foreach (string s in c)
                    {
                        interaction = interaction + " * " + s;
                    }

                    interaction = interaction.Remove(0, 3); //remove the first *

                    //add the interaction to the list
                    interactions.Add(interaction);
                }
            }

            return interactions;
        }


        private ObservableCollection<DataHandler> availableDataHandlers = new ObservableCollection<DataHandler>();
        public ObservableCollection<DataHandler> AvailableDataHandlers
        {
            get
            {
                return availableDataHandlers;
            }
            set
            {
                availableDataHandlers = value;
                NotifyPropertyChanged("AvailableDataHandlers");
            }
        }

        private DataHandler selectedDataHandler;
        public DataHandler SelectedDataHandler
        {
            get { return selectedDataHandler; }
            set
            {
                selectedDataHandler = value;
                NotifyPropertyChanged("SelectedDataHandler");
            }
        }


        private ObservableCollection<ColumnInfo> availableVariables = new ObservableCollection<ColumnInfo>();
        public ObservableCollection<ColumnInfo> AvailableVariables
        {
            get { return availableVariables; }
            set
            {
                availableVariables = value;
                NotifyPropertyChanged("AvailableVariables");
            }
        }

        private ObservableCollection<ColumnInfo> responseList = new ObservableCollection<ColumnInfo>();
        public ObservableCollection<ColumnInfo> ResponseList
        {
            get { return responseList; }
            set
            {
                responseList[0] = value[0];
                NotifyPropertyChanged("ResponseList");
            }
        }

        [CustomValidation(typeof(BasicGUIValidator), "CheckStringVarSet")]
        [Display(Name = "Response")]
        public string Response
        {
            get
            {
                if (responseList.Count == 1)
                    return responseList[0].ColumnName;
                else
                    return null;
            }
        }

        private ObservableCollection<ColumnInfo> treatments = new ObservableCollection<ColumnInfo>();
        [CustomValidation(typeof(BasicGUIValidator), "CheckListVarSet")]
        [Display(Name = "Treatments")]
        public ObservableCollection<ColumnInfo> Treatments
        {
            get { return treatments; }
            set
            {
                treatments = value;
                NotifyPropertyChanged("Treatments");
            }
        }

        public List<string> TreatmentColumnNames
        {
            get
            {
                List<string> names = new List<string>();

                foreach (ColumnInfo ci in treatments) names.Add(ci.ColumnName);
                return names;
            }
        }

        private ObservableCollection<ColumnInfo> otherDesignFactors = new ObservableCollection<ColumnInfo>();
        public ObservableCollection<ColumnInfo> OtherDesignFactors
        {
            get { return otherDesignFactors; }
            set
            {
                otherDesignFactors = value;
                NotifyPropertyChanged("OtherDesignFactors");
            }
        }

        public List<string> OtherDesignFactorColumnNames
        {
            get
            {
                List<string> names = new List<string>();

                foreach (ColumnInfo ci in otherDesignFactors) names.Add(ci.ColumnName);
                return names;
            }
        }

        private string responseTransformation = "None";
        public string ResponseTransformation
        {
            get { return responseTransformation; }
            set { responseTransformation = value; }
        }

        private List<string> transformationList = new List<string>() { "None", "Log10", "Loge", "Square Root", "ArcSine", "Rank" };
        public List<string> TransformationList
        {
            get { return transformationList; }
        }

        private ObservableCollection<string> interactions = new ObservableCollection<string>();
        public ObservableCollection<string> Interactions
        {
            get { return interactions; }
            set
            {
                interactions = value;
                NotifyPropertyChanged("Interactions");
            }
        }

        private ObservableCollection<ColumnInfo> covariateList = new ObservableCollection<ColumnInfo>();
        public ObservableCollection<ColumnInfo> CovariateList
        {
            get { return covariateList; }
            set
            {
                covariateList[0] = value[0];
                NotifyPropertyChanged("CovariateList");
            }
        }

        public string Covariate
        {
            get
            {
                if (covariateList.Count == 1)
                    return covariateList[0].ColumnName;
                else
                    return null;
            }
        }

        private ColumnInfo primaryFactor;
        public ColumnInfo PrimaryFactor
        {
            get { return primaryFactor; }
            set { primaryFactor = value; }
        }

        public string PrimaryFactorColumnName
        {
            get
            {
                if (primaryFactor != null)
                {
                    return primaryFactor.ColumnName;
                }
                else
                {
                    return null;
                }
            }
        }

        private string covariateTransformation = "None";
        public string CovariateTransformation
        {
            get { return covariateTransformation; }
            set { covariateTransformation = value; }
        }

        private bool anovaSelected = true;
        public bool ANOVASelected
        {
            get { return anovaSelected; }
            set
            {
                anovaSelected = value;
                NotifyPropertyChanged("ANOVASelected");
            }
        }

        private bool prPlotSelected = true;
        public bool PRPlotSelected
        {
            get { return prPlotSelected; }
            set
            {
                prPlotSelected = value;
                NotifyPropertyChanged("PRPlotSelected");
            }
        }

        private bool normalPlotSelected;
        public bool NormalPlotSelected
        {
            get { return normalPlotSelected; }
            set
            {
                normalPlotSelected = value;
                NotifyPropertyChanged("NormalPlotSelected");
            }
        }

        //private bool standardisedEffectsSelected;
        //public bool StandardisedEffectsSelected
        //{
        //    get { return standardisedEffectsSelected; }
        //    set
        //    {
        //        standardisedEffectsSelected = value;
        //        NotifyPropertyChanged("StandardisedEffectsSelected");
        //    }
        //}

        private string significance = "0.05";
        public string Significance
        {
            get { return significance; }
            set { significance = value; }
        }

        private List<string> significanceList = new List<string>() { "0.1", "0.05", "0.01", "0.001" };
        public List<string> SignificanceList
        {
            get { return significanceList; }
        }

        private ObservableCollection<string> selectedEffectList = new ObservableCollection<string>();
        public ObservableCollection<string> SelectedEffectList
        {
            get { return selectedEffectList; }
            set
            {
                selectedEffectList = value;
                NotifyPropertyChanged("SelectedEffectList");
            }
        }

        private string selectedEffect;
        public string SelectedEffect
        {
            get { return selectedEffect; }
            set
            {
                selectedEffect = value;
                NotifyPropertyChanged("SelectedEffect");

                if (!String.IsNullOrEmpty(selectedEffect) && !selectedEffect.Contains("*"))
                {
                    ControlGroupList = SelectedDataHandler.GetLevels(selectedEffect).ToObservableCollection();
                }
            }
        }

        private bool lsMeansPlotSelected;
        public bool LSMeansPlotSelected
        {
            get { return lsMeansPlotSelected; }
            set
            {
                lsMeansPlotSelected = value;
                NotifyPropertyChanged("LSMeansPlotSelected");
            }
        }

        private string allPairwise = String.Empty;
        public string AllPairwise
        {
            get { return allPairwise; }
            set { allPairwise = value; }
        }

        private List<string> postHocTestList = new List<string>() { "Unadjusted (LSD)", "Tukey", "Holm", "Hochberg", "Hommel", "Bonferonni", "Benjamini-Hochberg" };
        public List<string> PostHocTestList
        {
            get { return postHocTestList; }
        }

        private string comparisonsBackToControl = String.Empty;
        public string ComparisonsBackToControl
        {
            get { return comparisonsBackToControl; }
            set { comparisonsBackToControl = value; }
        }

        private string controlGroup = String.Empty;
        public string ControlGroup
        {
            get { return controlGroup; }
            set { controlGroup = value; }
        }

        private ObservableCollection<string> controlGroupList = new ObservableCollection<string>();
        public ObservableCollection<string> ControlGroupList
        {
            get { return controlGroupList; }
            set
            {
                controlGroupList = value;
                NotifyPropertyChanged("ControlGroupList");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        // NotifyPropertyChanged will raise the PropertyChanged event, passing the source property that is being updated.
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}